﻿///////////////////////////////////////////////////////////////////////////////
//
// wxFormBuilder - A Visual Dialog Editor for wxWidgets.
// Copyright (C) 2005 José Antonio Hurtado
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// Written by
//   José Antonio Hurtado - joseantonio.hurtado@gmail.com
//   Juan Antonio Ortega  - jortegalalmolda@gmail.com
//
///////////////////////////////////////////////////////////////////////////////

#include "stringutils.h"

#include "typeconv.h"
#include "wxfbexception.h"
#include <string>
#include "ticpp.h"
#include <QFileInfo>
#include <QMessageBox>

namespace StringUtils {

QString IntToStr(const int num) {
    QString result;
    //result.Printf(wxT("%d"), num);
	return result;
}

QString GetSupportedEncodings(bool columnateWithTab, QStringList* array) {
    QString result = "";
//	size_t count = wxFontMapper::GetSupportedEncodingsCount();
//	size_t max = 40;
//	for (size_t i = 0; i < count; ++i) {
//		wxFontEncoding encoding = wxFontMapper::GetEncoding(i);
//        QString name = wxFontMapper::GetEncodingName(encoding);
//		size_t length = name.length();
//		if (length > max) {
//			max = length + 10;
//		}
//		if (columnateWithTab) {
//			name = name.Pad((size_t)((max - length) / 8 + 1), wxT('\t'));
//		} else {
//			name = name.Pad(max - length);
//		}
//		name += wxFontMapper::GetEncodingDescription(encoding);
//		if (NULL != array) {
//			array->Add(name);
//		}
//		result += name;
//		result += wxT("\n");
//	}

	return result;
}

QString GetEncodingFromUser(const QString& message) {
//	wxArrayString array;
//	GetSupportedEncodings(false, &array);
//	int selection =
//	    ::wxGetSingleChoiceIndex(message, _("Choose an Encoding"), array, wxTheApp->GetTopWindow());
//	if (-1 == selection) {
//		return wxFONTENCODING_MAX;
//	}
//	return wxFontMapper::GetEncoding(selection);
    return QString();
}

std::string QString2string(const QString& src) {
//	wxCSConv cvGB2312(wxT("GB2312"));
//	return std::string(cvGB2312.cWX2MB(src.c_str()));
    return "";
}

QString string2QString(const std::string& src) {
//	wxCSConv cvGB2312(wxT("GB2312"));
//    return QString(cvGB2312.cMB2WX(src.c_str()));
    return "";
}
void remove_comment(char* str) {
	for(int i=0;str[i]!=EOF;i++){
		if(str[i]=='/'&&str[i+1]=='/'){
			str[i]='\0';
			str[i+1]='\0';
			break;
		}
	}
}
void remove_space(char* str) {
	int i,j,k;
	for(i=0;str[i]!=EOF;i++){//保留一个空格（"a    student"中在a和student之间只需保留一个空格） 
		if(str[i]==32&&str[i+1]==32)
		{
			k=i;
			for(j=i;str[j]!=EOF;j++)
			if(str[j]!=32)
			break;
			for(j;str[j]!=EOF;j++){
				str[k+1]=str[j];
				k++;
			}
		}	
	}
	if(str[0]==32){//处理字符串开头为空格（" a student"中a前面的空格应删去） 
		for(i=0;str[i]!=EOF;i++)
		str[i]=str[i+1];
	} 
	for(i=0;str[i]!=EOF;i++){//删去不用字符（“int m, n”中,和n之间的空格应删去） 
		if(str[i]==32){
			if(str[i-1]>='a'&&str[i-1]<='z'&&str[i+1]>='a'&&str[i+1]<='z')
			continue;
			else{
				for(j=i;str[j+1]!=EOF;j++)
				str[j]=str[j+1];
			}
		}
	}
}
void remove_cr_lf(char* str) {
	for(int i=0;str[i]!=EOF;i++){
		if(str[i]=='\n'||str[i]=='\r'){
			str[i]=32;
		}
	}
}
void remove_comment_space_cr_lf(char* str) {
	remove_comment(str);//注释 
	remove_space(str);//空格 
	remove_cr_lf(str);//回车和换行 
}


std::string remove_comment_space_cr_lf(std::string & src){
	char * psrc = new char[src.size() + 1];
	memset(psrc, 0, src.size() + 1);
    int count = 0;
    for(size_t i = 0; i<= src.size();i++)
    {
        //单行注释，直到遇到回车换行
        if(src[i]=='/'&&src[i+1]=='/')
        {
            while(src[i]!='\n' && src[i]!='\r')
            {
                i++;
            }
        }
        //多行注释
        if(src[i]=='/'&&src[i+1]=='*')
        {
            i+=2;
            while(src[i]!='*'||src[i+1]!='/')
            {
                i++;
                // if(src[i]=='$')
                // {
                //     printf("error");
                //     exit(0);
                // }
            }
            i += 2;
        }
        if (src[i] != '\n'&&src[i] != '\t'&&src[i] != '\v'&&src[i] != '\r')
        {//若出现无用字符，则过滤；否则加载
            psrc[count++] = src[i];
        }
    }
    psrc[count] = '\0';
	std::string dst(psrc);
	int s = dst.find_first_not_of(" ");
    int e = dst.find_last_not_of(" ");
    dst = dst.substr(s,e-s+1);
	//delete psrc;
	return dst;
}
} // namespace StringUtils

namespace XMLUtils
{
	template < class T, class U >
        void LoadXMLFileImp( T& doc, bool condenseWhiteSpace, const QString& path, U* declaration )
	{
		if ( NULL == declaration )
		{
			// Ask user to all wxFB to convert the file to UTF-8 and add the XML declaration
            QString msg = ("This xml file has no declaration.\n");
            msg 		+= ("Would you like BMDesigner to backup the file and convert it to UTF-8\?\n");
            msg			+= ("You will be prompted for an encoding.\n\n");
            msg			+= ("Path: ");
			msg			+= path;
            QMessageBox:: StandardButton result = QMessageBox::question( NULL, ("Missing Declaration"), msg, QMessageBox::Yes|QMessageBox::No);
            if ( QMessageBox::No == result )
			{
				// User declined, give up
                //THROW_WXFBEX( _("Missing Declaration on XML File: ") << path );
			}

			// User accepted, convert the file
//			wxFontEncoding chosenEncoding = StringUtils::GetEncodingFromUser( _("Please choose the original encoding.") );
//			if ( wxFONTENCODING_MAX == chosenEncoding )
//			{
//                //THROW_WXFBEX( _("Missing Declaration on XML File: ") << path );
//			}

//			ConvertAndAddDeclaration( path, chosenEncoding );

			// Reload
			LoadXMLFile( doc, condenseWhiteSpace, path );
			return;
		}

        // The file will have a declaration at this point
        QString version = _WXSTR( declaration->Version() );
        if ( version.isEmpty() )
        {
            version = ("1.0");
        }

//        QString standalone = _WXSTR( declaration->Standalone() );
//		if ( standalone.empty() )
//		{
//			standalone = wxT("yes");
//		}

//        QString encodingName = _WXSTR( declaration->Encoding() );
//		if ( encodingName.empty() )
//		{
//			// Ask user to all wxFB to convert the file to UTF-8 and add the XML declaration
//            QString msg = _("This xml file has no encoding specified.\n");
//			msg 		+= _("Would you like BMDesigner to backup the file and convert it to UTF-8\?\n");
//			msg			+= _("You will be prompted for an encoding.\n\n");
//			msg			+= _("Path: ");
//			msg			+= path;
//			if ( wxNO == wxMessageBox( msg, _("Unknown Encoding"), wxICON_QUESTION | wxYES_NO | wxYES_DEFAULT, wxTheApp->GetTopWindow() ) )
//			{
//				// User declined, give up
//				THROW_WXFBEX( _("Unknown Encoding for XML File: ") << path );
//			}

//			// User accepted, convert the file
//			wxFontEncoding chosenEncoding = StringUtils::GetEncodingFromUser( _("Please choose the original encoding.") );
//			if ( wxFONTENCODING_MAX == chosenEncoding )
//			{
//				THROW_WXFBEX( _("Unknown Encoding for XML File: ") << path );
//			}
//			ConvertAndChangeDeclaration( path, version, standalone, chosenEncoding );

//			// Reload
//			LoadXMLFile( doc, condenseWhiteSpace, path );
//			return;
//		}

//		// The file will have an encoding at this point
//		wxFontEncoding encoding = wxFontMapperBase::GetEncodingFromName( encodingName.MakeLower() );
//		if ( wxFONTENCODING_UTF8 == encoding )
//		{
//			// This is what we want
//			return;
//		}
//		else if ( wxFONTENCODING_MAX == encoding )
//		{
//            QString msg = QString::Format( _("The encoding of this xml file is not supported.\n\nFile: %s\nEncoding: %s\nSupported Encodings:\n\n%s"),
//							path.c_str(),
//							encodingName.c_str(),
//							StringUtils::GetSupportedEncodings().c_str() );
//            wxMessageBox( msg, QString::Format( _("Unsupported Encoding: %s"), encodingName.c_str() ) );
//			THROW_WXFBEX( _("Unsupported encoding for XML File: ") << path );
//		}
//		else
//		{
//			// Ask user to all wxFB to convert the file to UTF-8 and add the XML declaration
//            QString msg = QString::Format( _("This xml file has specified encoding %s. BMDesigner only works with UTF-8.\n"),
//							wxFontMapper::GetEncodingDescription( encoding ).c_str() );
//			msg 		+= _("Would you like BMDesigner to backup the file and convert it to UTF-8\?\n\n");
//			msg			+= _("Path: ");
//			msg			+= path;
//			if ( wxNO == wxMessageBox( msg, _("Not UTF-8"), wxICON_QUESTION | wxYES_NO | wxYES_DEFAULT, wxTheApp->GetTopWindow() ) )
//			{
//				// User declined, give up
//				THROW_WXFBEX( _("Wrong Encoding for XML File: ") << path );
//			}

//			// User accepted, convert the file
//			ConvertAndChangeDeclaration( path, version, standalone, encoding );

//			// Reload
//			LoadXMLFile( doc, condenseWhiteSpace, path );
//			return;
//		}
	}
}

void XMLUtils::LoadXMLFile( ticpp::Document& doc, bool condenseWhiteSpace, const QString& path )
{
    try
    {
        if ( path.isEmpty() )
        {
            THROW_WXFBEX( _("LoadXMLFile needs a path") )
        }

        QFileInfo fi(path);
        if ( !fi.isFile() )
        {
            THROW_WXFBEX( _("The file does not exist.\nFile: ") << path )
        }
        TiXmlBase::SetCondenseWhiteSpace( condenseWhiteSpace );
        doc.SetValue( std::string( path.toLocal8Bit().constData() ) );
        doc.LoadFile();
    }
    catch ( ticpp::Exception& )
    {
        // Ask user to all wxFB to convert the file to UTF-8 and add the XML declaration
        QString msg = ("This xml file could not be loaded. This could be the result of an unsupported encoding.\n");
        msg 		+= ("Would you like BMDesigner to backup the file and convert it to UTF-8\?\n");
        msg			+= ("You will be prompted for the original encoding.\n\n");
        msg			+= ("Path: ");
        msg			+= path;
//		if ( wxNO == wxMessageBox( msg, _("Unable to load file"), wxICON_QUESTION | wxYES_NO | wxYES_DEFAULT, wxTheApp->GetTopWindow() ) )
//		{
//			// User declined, give up
//			THROW_WXFBEX( _("Unable to load file: ") << path );
//		}
        QMessageBox::critical(nullptr, "Error", "Unable to load file!");

//		// User accepted, convert the file
//		wxFontEncoding chosenEncoding = StringUtils::GetEncodingFromUser( _("Please choose the original encoding.") );
//		if ( wxFONTENCODING_MAX == chosenEncoding )
//		{
//			THROW_WXFBEX( _("Unable to load file: ") << path );
//		}

//		ConvertAndAddDeclaration( path, chosenEncoding );

        LoadXMLFile( doc, condenseWhiteSpace, path );
    }
    ticpp::Declaration* declaration;
    try
    {
        ticpp::Node* firstChild = doc.FirstChild();
        declaration = firstChild->ToDeclaration();
    }
    catch( ticpp::Exception& )
    {
        declaration = NULL;
    }
    LoadXMLFileImp( doc, condenseWhiteSpace, path, declaration );
}

void XMLUtils::LoadXMLFile( TiXmlDocument& doc, bool condenseWhiteSpace, const QString& path )
{
    if ( path.isEmpty() )
    {
        THROW_WXFBEX( _("LoadXMLFile needs a path") )
    }
    QFileInfo fi(path);
    if ( !fi.isFile() )
    {
        THROW_WXFBEX( _("The file does not exist.\nFile: ") << path )
    }

    TiXmlBase::SetCondenseWhiteSpace( condenseWhiteSpace );
    doc.SetValue( std::string( path.toLocal8Bit().constData() ) );
    if ( !doc.LoadFile() )
    {
        // Ask user to all wxFB to convert the file to UTF-8 and add the XML declaration
        QString msg = ("This xml file could not be loaded. This could be the result of an unsupported encoding.\n");
        msg 		+= ("Would you like BMDesigner to backup the file and convert it to UTF-8\?\n");
        msg			+= ("You will be prompted for the original encoding.\n\n");
        msg			+= ("Path: ");
        msg			+= path;
//		if ( wxNO == wxMessageBox( msg, _("Unable to load file"), wxICON_QUESTION | wxYES_NO | wxYES_DEFAULT, wxTheApp->GetTopWindow() ) )
//		{
//			// User declined, give up
//			THROW_WXFBEX( _("Unable to load file: ") << path );
//		}
        QMessageBox::critical(nullptr, "Error", "Unable to load file!");
//		// User accepted, convert the file
//		wxFontEncoding chosenEncoding = StringUtils::GetEncodingFromUser( _("Please choose the original encoding.") );
//		if ( wxFONTENCODING_MAX == chosenEncoding )
//		{
//			THROW_WXFBEX( _("Unable to load file: ") << path );
//		}

//		ConvertAndAddDeclaration( path, chosenEncoding );

        LoadXMLFile( doc, condenseWhiteSpace, path );
    }

    TiXmlDeclaration* declaration = NULL;
    TiXmlNode* firstChild = doc.FirstChild();
    if ( firstChild )
    {
        declaration = firstChild->ToDeclaration();
    }
    LoadXMLFileImp( doc, condenseWhiteSpace, path, declaration );
}


//void XMLUtils::ConvertAndAddDeclaration( const QString& path, wxFontEncoding encoding, bool backup )
//{
//	ConvertAndChangeDeclaration( path, wxT("1.0"), wxT("yes"), encoding, backup );
//}

//void XMLUtils::ConvertAndChangeDeclaration( const QString& path, const QString& version, const QString& standalone, wxFontEncoding encoding, bool backup )
//{
//	// Backup the file
//	if ( backup )
//	{
//		if ( !::wxCopyFile( path, path + wxT(".bak") ) )
//		{
//            QString msg = QString::Format( _("Unable to backup file.\nFile: %s\nBackup: %s.bak"), path.c_str(), path.c_str() );
//			THROW_WXFBEX( msg )
//		}
//	}

//	// Read the entire contents into a string
//	wxFFile oldEncoding( path.c_str(), wxT("src") );
//    QString contents;
//	wxCSConv encodingConv( encoding );
//	if ( !oldEncoding.ReadAll( &contents, encodingConv ) )
//	{
//        QString msg = QString::Format( _("Unable to read the file in the specified encoding.\nFile: %s\nEncoding: %s"), path.c_str(), wxFontMapper::GetEncodingDescription( encoding ).c_str() );
//		THROW_WXFBEX( msg );
//	}

//	if ( contents.empty() )
//	{
//        QString msg = QString::Format( _("The file is either empty or read with the wrong encoding.\nFile: %s\nEncoding: %s"), path.c_str(), wxFontMapper::GetEncodingDescription( encoding ).c_str() );
//		THROW_WXFBEX( msg );
//	}

//	if ( !oldEncoding.Close() )
//	{
//        QString msg = QString::Format( _("Unable to close original file.\nFile: %s"), path.c_str() );
//		THROW_WXFBEX( msg );
//	}

//	// Modify the declaration, so TinyXML correctly determines the new encoding
//	int declStart = contents.Find( wxT("<\?") );
//	int declEnd = contents.Find( wxT("\?>") );
//	if ( wxNOT_FOUND == declStart && wxNOT_FOUND == declEnd )
//	{
//		int firstElement = contents.Find( wxT("<") );
//		if ( wxNOT_FOUND == firstElement )
//		{
//			firstElement = 0;
//		}
//        contents.insert( firstElement, QString::Format( wxT("<\?xml version=\"%s\" encoding=\"UTF-8\" standalone=\"%s\" \?>\n"), version.c_str(), standalone.c_str() ) );
//	}
//	else
//	{
//		if ( wxNOT_FOUND == declStart )
//		{
//            QString msg = QString::Format( _("Found a declaration end tag \"\?>\" but could not find the start \"<\?\".\nFile: %s"), path.c_str() );
//			THROW_WXFBEX( msg );
//		}

//		if ( wxNOT_FOUND == declEnd )
//		{
//            QString msg = QString::Format( _("Found a declaration start tag \"<\?\" but could not find the end \"\?>\".\nFile: %s"), path.c_str() );
//			THROW_WXFBEX( msg );
//		}

//		// declStart and declEnd are both valid, replace that section with a new declaration
//		contents.replace(
//		    declStart, declEnd - declStart + 2,
//            QString::Format(wxT("<\?xml version=\"%s\" encoding=\"UTF-8\" standalone=\"%s\" \?>"),
//		                     version, standalone));
//	}

//	// Remove the old file
//	if ( !::wxRemoveFile( path ) )
//	{
//        QString msg = QString::Format( _("Unable to delete original file.\nFile: %s"), path.c_str() );
//		THROW_WXFBEX( msg );
//	}

//	// Write the new file
//	wxFFile newEncoding( path.c_str(), wxT("w") );
//	if ( !newEncoding.Write( contents, wxConvUTF8 ) )
//	{
//        QString msg = QString::Format( _("Unable to write file in its new encoding.\nFile: %s\nEncoding: %s"), path.c_str(), wxFontMapper::GetEncodingDescription( wxFONTENCODING_UTF8 ).c_str() );
//		THROW_WXFBEX( msg );
//	}

//	if ( !newEncoding.Close() )
//	{
//        QString msg = QString::Format( _("Unable to close file after converting the encoding.\nFile: %s\nOld Encoding: %s\nNew Encoding: %s"),
//											path.c_str(),
//											wxFontMapper::GetEncodingDescription( encoding ).c_str(),
//											wxFontMapper::GetEncodingDescription( wxFONTENCODING_UTF8 ).c_str() );
//		THROW_WXFBEX( msg );
//	}
//}
